/* * Copyright (c) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.JsonFactory; import com.google.common.base.Preconditions; import java.awt.Desktop; import java.awt.Desktop.Action; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; /** * Implements OAuth authentication "native" flow recommended for installed clients in which the end * user must grant access in a web browser and then copy a code into the application. * * <p> * The client_secrets.json file contains your client application's client ID and client secret. They * can be found in the <a href="https://code.google.com/apis/console/">Google APIs Console</a>. If * this is your first time, click "Create project...". Then, activate the Google APIs your client * application uses and agree to the terms of service. Now, click on "API Access", and then on * "Create an OAuth 2.0 Client ID...". Enter a product name and click "Next". >Select "Installed * application" and click "Create client ID". Finally, enter the "Client ID" and "Client secret" * shown under "Client ID for installed applications" into * {@code src/main/resources/client_secrets.json}. * </p> * * <p> * Warning: the client ID and secret are not secured and are plainly visible to users of your * application. It is a hard problem to secure client credentials in installed applications. * </p> * * <p> * In this sample code, it attempts to open the browser using {@link Desktop#isDesktopSupported()}. * If that fails, on Windows it tries {@code rundll32}. If that fails, it opens the browser * specified in {@link #BROWSER}, though note that currently we've only tested this code with Google * Chrome (hence this is the default value). * </p> * * @author Yaniv Inbar */ public class OAuth2Native { private static final String RESOURCE_LOCATION = "client_secrets.json"; private static final String RESOURCE_PATH = ("shared/shared-sample-cmdline/src/main/resources" + RESOURCE_LOCATION).replace( '/', File.separatorChar); /** * Browser to open in case {@link Desktop#isDesktopSupported()} is {@code false} or {@code null} * to prompt user to open the URL in their favorite browser. */ private static final String BROWSER = "google-chrome"; /** Google client secrets or {@code null} before initialized in {@link #authorize}. */ private static GoogleClientSecrets clientSecrets = null; /** Returns the Google client secrets or {@code null} before initialized in {@link #authorize}. */ public static GoogleClientSecrets getClientSecrets() { return clientSecrets; } /** * Loads the Google client secrets (if not already loaded). * * @param jsonFactory JSON factory */ private static GoogleClientSecrets loadClientSecrets(JsonFactory jsonFactory) throws IOException { if (clientSecrets == null) { InputStream inputStream = OAuth2Native.class.getResourceAsStream(RESOURCE_LOCATION); Preconditions.checkNotNull(inputStream, "missing resource %s", RESOURCE_LOCATION); clientSecrets = GoogleClientSecrets.load(jsonFactory, inputStream); Preconditions.checkArgument(!clientSecrets.getDetails().getClientId().startsWith("[[") && !clientSecrets.getDetails().getClientSecret().startsWith("[["), "Please enter your client ID and secret from the Google APIs Console in %s from the " + "root samples directory", RESOURCE_PATH); } return clientSecrets; } /** * Authorizes the installed application to access user's protected data. * * @param transport HTTP transport * @param jsonFactory JSON factory * @param receiver verification code receiver * @param scopes OAuth 2.0 scopes */ public static Credential authorize(HttpTransport transport, JsonFactory jsonFactory, VerificationCodeReceiver receiver, Iterable<String> scopes, File cred) throws Exception { try { String redirectUri = receiver.getRedirectUri(); GoogleClientSecrets clientSecrets = loadClientSecrets(jsonFactory); // redirect to an authorization page // TODO(mlinder, 1.11.0-beta): Use setAccessType("offline").setApprovalPrompt("force") with // FileCredentialStore. FileCredentialStore fcs = new FileCredentialStore(cred , jsonFactory); GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( transport, jsonFactory, clientSecrets, scopes).setAccessType("offline") .setApprovalPrompt("auto").setCredentialStore(fcs).build(); //.setAccessType("online") //.setApprovalPrompt("auto").build(); Credential c = flow.loadCredential("datascienceresearch@gmail.com"); if (c != null) return c; else { browse(flow.newAuthorizationUrl().setRedirectUri(redirectUri).build()); // receive authorization code and exchange it for an access token String code = receiver.waitForCode(); GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(redirectUri).execute(); // store credential and return it return flow.createAndStoreCredential(response, "datascienceresearch@gmail.com"); } //System.out.println(flow.getCredentialStore()); //; //return c; } finally { receiver.stop(); } } /** Open a browser at the given URL. */ private static void browse(String url) { // first try the Java Desktop if (Desktop.isDesktopSupported()) { Desktop desktop = Desktop.getDesktop(); if (desktop.isSupported(Action.BROWSE)) { try { desktop.browse(URI.create(url)); return; } catch (IOException e) { // handled below } } } // Next try rundll32 (only works on Windows) try { Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); return; } catch (IOException e) { // handled below } // Next try the requested browser (e.g. "google-chrome") if (BROWSER != null) { try { Runtime.getRuntime().exec(new String[] {BROWSER, url}); return; } catch (IOException e) { // handled below } } // Finally just ask user to open in their browser using copy-paste System.out.println("Please open the following URL in your browser:"); System.out.println(" " + url); } private OAuth2Native() { } }